package com.example.villagemarket;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONException;

import com.example.villagemarket.adapter.*;
import com.haarman.listviewanimations.swinginadapters.prepared.ScaleInAnimationAdapter;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;

import android.view.Menu;

import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SearchView;

import android.widget.TextView;
import android.widget.Toast;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.app.SearchManager;

public class MainActivity extends FragmentActivity implements
		ActionBar.TabListener {

	// Tab Names. If the need arises to add more in the future,
	// Make sure to change the getCount() method in the TabsPagerAdapter.java
	// and make a fragment for the tab, and add a case for it in the getItem()
	// function
	private String[] tabs = { "Search", "Food Schedule", "Location" };

	// ID for the plus sign that is in each list item
	private static Integer ADD_TO_CART_IMAGE_ID = R.drawable.add_to_cart;

	// List that holds all of the items
	private List<Map<String, String>> itemHolder;

	// Variables needed for tabs
	private ViewPager viewPager;
	private TabsPagerAdapter mAdapter;
	private ActionBar actionBar;

	// Used to make toasts where the context isn't otherwise reachable
	Context c;

	// Used so the badge count on the cart can keep it's state when
	// an orientation change occurs
	private Menu currentMenu;

	// Stores the names of the search results when it finishes in the asynch
	// task
	private String itemNames;

	// Stores if it's the first time a user is using the app
	SharedPreferences sharedPref;

	/**
	 * Stores the context for later use in a Toast and initializes and adds the
	 * tabs.
	 * 
	 * @param Bundle
	 *            : the state the app was in before onCreate is called
	 * @return void
	 * @see Bundle
	 */

	public void showPopup(View v) {
		sharedPref = getSharedPreferences("firstTime",MODE_PRIVATE);
		if (!sharedPref.contains("firstTime")) {

			ChromeHelpPopup chromeHelpPopup = new ChromeHelpPopup(
					MainActivity.this,
					"Enter a search term above to get started!");
			chromeHelpPopup.show(v);

			Editor editor = sharedPref.edit();

			editor.putBoolean("firstTime", false);

			editor.commit();

		} 
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// Storing the Main activity's context for use in toasts
		c = this;

		// Initilization of tabs
		viewPager = (ViewPager) findViewById(R.id.pager);
		actionBar = getActionBar();
		mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
		viewPager.setAdapter(mAdapter);


		// Remove title from actionbar
		actionBar.setDisplayShowTitleEnabled(false);

		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		// Adding Tabs
		for (String tab_name : tabs) {
			actionBar.addTab(actionBar.newTab().setText(tab_name)
					.setTabListener(this));
		}

		// Add listener for changing tabs
		viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

			@Override
			public void onPageSelected(int position) {
				// changes tab to selected one
				actionBar.setSelectedNavigationItem(position);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int arg0) {
			}
		});

	}

	/**
	 * Checks to see if the menu is null, and if it is not, it updates the
	 * shopping cart to show how many items are in the shopping cart.
	 * 
	 * 
	 * @return void
	 */
	@Override
	public void onResume() {
		super.onResume();

		if (currentMenu != null) {
			updateNotificationNumber();
		}

	}

	/**
	 * Inflates the menu. Adds a click listener to the shopping cart item. When
	 * the shopping cart is touched, it will open up the ViewShoppingCart class.
	 * 
	 * Sets up and adds a click listener to the magnifying glassin the action
	 * bar and calls the method to search the database
	 * 
	 * 
	 * @param Menu
	 *            : the current menu
	 * @return boolean: returns whether or not the menu was successfully
	 *         inflated
	 * @see Menu
	 */

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);

		// Store the main activity's menu for later use
		currentMenu = menu;
		ShoppingCart.menu = currentMenu;

		// sets the onclick listener for the cart button that opens up the
		// shopping cart activity

		menu.findItem(R.id.shoppingCart).getActionView()
				.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						Intent sc = new Intent(getApplicationContext(),
								ViewShoppingCart.class);
						sc.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
						startActivity(sc);

					}
				});

		// Associate searchable configuration with the SearchView
		SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
		SearchView searchView = (SearchView) menu.findItem(R.id.search)
				.getActionView();
		searchView.setSearchableInfo(searchManager
				.getSearchableInfo(getComponentName()));
		searchView.getQuery();

		// Add listener for the search in the actionbar
		SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
			public boolean onQueryTextChange(String newText) {
				// Toast.makeText(c, "Searching...", Toast.LENGTH_SHORT).show();

				return true;
			}

			// This is fired when the user presses the search button on the
			// keyboard in the search
			// in the actionbar
			public boolean onQueryTextSubmit(String query) {

				// Sets the tab to the first tab when the user hits select
				// to help avoid any errors.
				actionBar.setSelectedNavigationItem(0);

				// clears the "Enter item to search" text view
				TextView tv = (TextView) findViewById(R.id.enterSearch);
				tv.setText("Searching...");
				
				tv = (TextView) findViewById(R.id.textView1);
				tv.setText("");
				
				tv = (TextView) findViewById(R.id.textView2);
				tv.setText("");
				
				tv = (TextView) findViewById(R.id.textView3);
				tv.setText("");

				// Searches the database
				searchDatabase(query);

				return false;

			}
		};

		// Set listener for search
		searchView.setOnQueryTextListener(queryTextListener);

		updateNotificationNumber();

		Button b = (Button) findViewById(R.id.button1);
		b.performClick();

		return super.onCreateOptionsMenu(menu);

	}

	/**
	 * When a tab is selected, the viewPager moves to the selected tab.
	 * 
	 * 
	 * @param Tab
	 *            : the tab that was selected
	 * @param FragmentTransaction
	 *            : the action of selectig the tab
	 * @return void
	 * @see Menu
	 */
	@Override
	public void onTabSelected(Tab arg0, FragmentTransaction arg1) {
		// on tab selected
		// show respected fragment view
		viewPager.setCurrentItem(arg0.getPosition());

	}

	/**
	 * Checks to see if the user has either a wifi or a mobile connection
	 * 
	 * 
	 * @return boolean: a boolean representing if the user has either a wifi or
	 *         a mobile connection
	 * @see Menu
	 */
	private boolean haveNetworkConnection() {
		boolean haveConnectedWifi = false;
		boolean haveConnectedMobile = false;

		ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo[] netInfo = cm.getAllNetworkInfo();
		for (NetworkInfo ni : netInfo) {
			if (ni.getTypeName().equalsIgnoreCase("WIFI"))
				if (ni.isConnected())
					haveConnectedWifi = true;
			if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
				if (ni.isConnected())
					haveConnectedMobile = true;
		}
		return haveConnectedWifi || haveConnectedMobile;
	}

	/**
	 * Calls the asynch task that searches the database for the search results
	 * 
	 * 
	 * @param String
	 *            : the entered search parameter
	 * @return void
	 * @see Menu
	 */
	public void searchDatabase(String searchFor) {

		// Make sure user has connection first, else a toast is displayed
		if (haveNetworkConnection()) {

			// Returned in the format of
			// description:Quantity:Price:PriceA from php page
			new getResults().execute(searchFor);

		} else {
			Toast.makeText(getApplicationContext(),
					"There is no network connection!", Toast.LENGTH_SHORT)
					.show();

		}

	}

	/**
	 * Helper method to add a hashmap to an arraylist to store the underlying
	 * data structure for the list
	 * 
	 * 
	 * @param String
	 *            : The key for the returned hash map
	 * @param String
	 *            : The value for the returned hashmap
	 * @return HashMap: returns a hashmap containing the key/value pair
	 * @see HashMap
	 */
	private HashMap<String, String> addItem(String key, String name) {
		HashMap<String, String> x = new HashMap<String, String>();
		x.put(key, name);

		return x;
	}

	/**
	 * Async class that searches the database asynchronously for the search term
	 * that the user entered. Parses the returned JSON. Populates the parsed
	 * JSON into a data structure that the listview can use.
	 * 
	 * 
	 * @param String
	 *            : The string the user searched for
	 * @param Context
	 *            : The context that is passed for the adapter to use
	 * @param String
	 *            : The results that are passed to the onPostExecute method
	 * @see HashMap
	 */
	public class getResults extends AsyncTask<String, Context, String> {

		@Override
		protected String doInBackground(String... params) {
			String[] parameters = new String[1];

			parameters[0] = params[0];

			HTTPPost hp = new HTTPPost(parameters,
					"http://worthagoogle.brosnetwork.co.uk/android_php/VM/search.php");

			return hp.responseString;

		}

		@Override
		protected void onPostExecute(String values) {

			itemHolder = new ArrayList<Map<String, String>>();
			ArrayList<String> names = new ArrayList<String>();

			itemNames = values;

			// Parses the returned values from search.php
			try {

				JsonParser jp = new JsonParser();

				names = jp.parse(itemNames);

				for (int i = 0; i < names.size(); i++) {
					itemHolder.add(addItem("item", names.get(i)));
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// If the results size is 0, display the error message
			// and clear the old list view in case the user has
			// done a search already
			if (names.size() == 0) {
				TextView tv = (TextView) findViewById(R.id.enterSearch);
				tv.setText("No results found");

				// Grabs the list view, populates it, sets up the adapter, and
				// adds the animation
				ListView list = (ListView) findViewById(R.id.resultList);

				ResultListView rlv = new ResultListView();

				ArrayList<HashMap<String, String>> items = rlv
						.populateListView(itemHolder, list,
								ADD_TO_CART_IMAGE_ID);

				ResultsAdapter ad = new ResultsAdapter(c, items, (Activity) c,
						ShoppingCart.menu);

				ScaleInAnimationAdapter ScaleInAnimationAdapter = new ScaleInAnimationAdapter(
						ad);

				ScaleInAnimationAdapter.setAbsListView(list);
				list.setAdapter(ScaleInAnimationAdapter);
			} else {
				// Grabs the list view, populates it, sets up the adapter, and
				// adds the animation
				ListView list = (ListView) findViewById(R.id.resultList);

				ResultListView rlv = new ResultListView();

				ArrayList<HashMap<String, String>> items = rlv
						.populateListView(itemHolder, list,
								ADD_TO_CART_IMAGE_ID);

				ResultsAdapter ad = new ResultsAdapter(c, items, (Activity) c,
						ShoppingCart.menu);

				ScaleInAnimationAdapter ScaleInAnimationAdapter = new ScaleInAnimationAdapter(
						ad);

				ScaleInAnimationAdapter.setAbsListView(list);
				list.setAdapter(ScaleInAnimationAdapter);

				// clears the "Enter item to search" text view
				TextView tv = (TextView) findViewById(R.id.enterSearch);
				tv.setText("");
			}

		}
	}

	/**
	 * Called when the user adds an item to the cart or the badge notification
	 * number needs to be updated
	 * 
	 * 
	 * 
	 * @return void
	 * @see HashMap
	 */
	public void updateNotificationNumber() {

		TextView badgeCount = (TextView) currentMenu
				.findItem(R.id.shoppingCart).getActionView()
				.findViewById(R.id.actionbar_notifcation_textview);
		if (ShoppingCart.items.size() > 0) {
			badgeCount.setVisibility(View.VISIBLE);

			badgeCount.setText(" " + ShoppingCart.items.size() + " ");
		} else {
			badgeCount.setVisibility(View.INVISIBLE);

			badgeCount.setText(" " + 0 + " ");
		}

	}

	@Override
	public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
	}

	@Override
	public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
		// TODO Auto-generated method stub

	}

	/**
	 * Starts the telephone call when the user presses on the image of the
	 * telephone
	 * 
	 * 
	 * 
	 * @return void
	 */
	public void callVillageMarket(View v) {
		Intent intent = new Intent(Intent.ACTION_CALL);
		intent.setData(Uri.parse("tel:920-922-2265"));
		startActivity(intent);
	}

}
